﻿#include "FITKAbaqusAdaptorMaterialElastic.h"
#include "InpKeyLineSpliter.h"

#include "FITKAbaqusINPReader.h"
#include "FITKAbaqusINPWriter.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMaterial.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaMaterialElastic.h"
namespace IO
{

    QString FITKAbaqusAdaptorMaterialElastic::getAdaptorClass()
    {
        return "IO::FITKAbaqusAdaptorMaterialElastic";
    }

    bool FITKAbaqusAdaptorMaterialElastic::adaptR()
    {
        _materialData = dynamic_cast<Interface::FITKAbaMaterial*>(_dataObj);
        if (!_materialData || !_reader) return false;

        //回退一行 处理关键字信息 校验
        _reader->backLine();
        //创建并获取数据
        Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType materialType =
            Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic;
        QString line = _reader->readLine();
        if (!line.toLower().startsWith("*elastic")) return false;
        bool create = _materialData->addMaterialBehavior(materialType);
        if (!create) return false;
        bool readOK = false;
        //关键字处理
        InpKeyLineSpliter s(line, _reader);
        //模量时间尺度
        if (s.hasKey("moduli") && s["moduli"].toUpper() == "INSTANTANEOUS")
        {//瞬态

        }
        else
        {//长期

        }
        //场变量个数
        if (s.hasKey("dependencies"))
        {
            this->_dependencies = s["dependencies"].trimmed().toInt(&readOK);
            if (!readOK)return false;
        }
        //获取类型
        QString type = s["type"].trimmed().toUpper();
        if (type.isEmpty() || type == "ISOTROPIC")
            readOK = this->readTypeIsotroplc();
        else if (type == "ENGINEERING CONSTANTS")
            readOK = this->readTypeEngineeringConstants();
        else if (type == "LAMINA")
            readOK = this->readTypeLamina();
        else if (type == "ORTHOTROPIC")
            readOK = this->readTypeOrthotropics();
        else if (type == "ANISOTROPIC")
            readOK = this->readTypeAnIsotopic();
        else if (type == "TRACTION")
            readOK = this->readTypeTraction();
        else if (type == "COUPLED TRACTION")
            readOK = this->readTypeCoupledTraction();
        else if (type == "SHEAR")
            readOK = this->readTypeShear();
        if (!readOK)
            _materialData->removeMaterialBehavior(materialType);
        return readOK;
    }

    bool FITKAbaqusAdaptorMaterialElastic::adaptW()
    {
        Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType materialType =
            Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic;
        _materialData = dynamic_cast<Interface::FITKAbaMaterial*>(_dataObj);
        if (!_materialData || !_writer) return false;
        //获得数据结构
        auto tempElastic = _materialData->getMaterialBehavior(materialType);
        //材料为空则返回
        if (!tempElastic) return true;
        auto elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        bool writeOK = false;
        //获取类型
        Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType type = elasticData->getMaterialElasticType();
        if (type == Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::IsoTropic)
            writeOK = this->writeTypeIsotroplc();
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::EngineeringConstants)
            writeOK = this->writeTypeEngineeringConstants();
        else if (type == Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::Lamina)
            writeOK = this->writeTypeLamina();
        return writeOK;
    }

    bool FITKAbaqusAdaptorMaterialElastic::readTypeIsotroplc()
    {
        if (!_materialData)return false;
        auto tempElastic = _materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic);
        if (!tempElastic)return false;
        //获取数据
        Interface::FITKAbaMaterialElastic* elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //设置类型
        elasticData->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::IsoTropic);
        //杨氏模量
        QVector<double> IsotropicYoungsModulus;
        //泊松比
        QVector<double> setIsotropicPoissonRatio;
        //温度
        QVector<double> setTemperature;
        //字段变量
        QVector<double> fieldVariable;

        bool readOK = false;
        //用于判断解析每行数据是否成功
        bool ok1 = false;
        bool ok2 = false;

        //解析 代码段
        while (!_reader->atEnd())
        {
            QString line = _reader->readLine();
            if (line.trimmed().isEmpty())continue;
            //关键字处理
            InpKeyLineSpliter tempS(line, _reader);
            QString str = tempS.getHeader().toLower();
            //处理不可压缩和不可拉伸
            if (str == "no compression")
            {
                elasticData->setNoCompression(true);
                continue;
            }
            else if (str == "no tension")
            {
                elasticData->setNoTension(true);
                continue;
            }
            //关键字 段落结束
            else if (line.startsWith("*"))
            {
                readOK = true;
                break;
            }
            if (line.endsWith(','))line.chop(1);
            QStringList sList = line.split(",");
            if (sList.size() < 2)
            {
                //可能的异常判断
                readOK = false;
                break;
            }

            //声明 杨氏模量 泊松比 温度
            double youngsModulus, poissonRatio, temperature;
            for (int i = 0; i < sList.size(); ++i)
            {
                if (sList[i].trimmed().isEmpty()) continue;
                if (i == 0) youngsModulus = sList[0].toDouble(&ok1);
                else if (i == 1) poissonRatio = sList[1].toDouble(&ok2);
                //温度这有可能有问题 待确认
                else if (i == 2)
                {
                    elasticData->setUseTemperatureDependentData(true);
                    temperature = sList[2].toDouble();
                }
                else if (i > 2) fieldVariable.append(sList[i].toDouble());
            }
            //if (!ok1 || !ok2) return false; 暂时注释后续无用则删除
            IsotropicYoungsModulus.append(youngsModulus);
            setIsotropicPoissonRatio.append(poissonRatio);
            setTemperature.append(temperature);
        }
        if (readOK || _reader->atEnd())
        {
            elasticData->setIsotropicNumberOfRows(IsotropicYoungsModulus.size());
            //elasticData->setEngineeringConstantsNumberOfRows(setTemperature.size());
            for (int i = 0; i < IsotropicYoungsModulus.size(); ++i)
            {
                elasticData->setIsotropicYoungsModulus(IsotropicYoungsModulus[i], i);
                elasticData->setIsotropicPoissonRatio(setIsotropicPoissonRatio[i], i);
                elasticData->setIsotropicTemperature(setTemperature[i], i);
            }
            return true;
        }
        return false;
    }

    bool FITKAbaqusAdaptorMaterialElastic::readTypeEngineeringConstants()
    {
        if (!_materialData)return false;
        auto tempElastic = _materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic);
        if (!tempElastic)return false;
        //获取数据
        Interface::FITKAbaMaterialElastic* elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //设置类型
        elasticData->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::EngineeringConstants);
        //文件应有的一次数据所具有的行数
        int row = (10 + _dependencies) % 8 ? (10 + _dependencies) / 8 + 1 : (10 + _dependencies) / 8;
        //初始化设置温度为true-为确保下面读取正常
        elasticData->setUseTemperatureDependentData(true);

        QString line;
        bool ok = false;
        int  num = 0;
        int index = 0;
        bool isTemperature = false;
        while (!_reader->atEnd())
        {
            line = _reader->readLine().trimmed();
            if (line.startsWith("*"))break;
            elasticData->setEngineeringConstantsNumberOfRows(index + 1);
            //移除最后一个,预防干扰
            if (line.endsWith(','))line.chop(1);
            QStringList str;
            if (!line.trimmed().isEmpty())
                str = line.trimmed().split(',');
            for (int j = 0; j < 8 && j < str.size(); ++j)
            {
                ++num;
                if (num == 10)
                    if (str.at(j).trimmed().isEmpty())
                        continue;
                    else
                        isTemperature = true;
                
                //读取数据
                double v = str.at(j).trimmed().toDouble(&ok);
                if (!ok)return false;
                //E1
                if (num == 1)
                    elasticData->setEngineeringConstantsE1(v, index);
                //E2
                else if (num == 2)
                    elasticData->setEngineeringConstantsE2(v, index);
                //E3
                else if (num == 3)
                    elasticData->setEngineeringConstantsE3(v, index);
                //Nu12
                else if (num == 4)
                    elasticData->setEngineeringConstantsNu12(v, index);
                //Nu13
                else if (num == 5)
                    elasticData->setEngineeringConstantsNu13(v, index);
                //Nu23
                else if (num == 6)
                    elasticData->setEngineeringConstantsNu23(v, index);
                //G12
                else if (num == 7)
                    elasticData->setEngineeringConstantsG12(v, index);
                //G13
                else if (num == 8)
                    elasticData->setEngineeringConstantsG13(v, index);
                //G23
                else if (num == 9)
                    elasticData->setEngineeringConstantsG23(v, index);
                //Temperature
                else if (num == 10)
                    elasticData->setEngineeringConstantsTemperature(v, index);
            }
            if (num % 8 != 0 || num / 8 == row)
            {
                ++index;
                if (num < 9)return false;
                num = 0;
            }
        }
        //再次设置温度确保数据正确
        elasticData->setUseTemperatureDependentData(isTemperature);
        //无压缩与无拉伸
        while (!_reader->atEnd())
        {
            if (line.toLower() == "*no compression")
                elasticData->setNoCompression(true);
            else if (line.toLower() == "*no tension")
                elasticData->setNoTension(true);
            else if (line.startsWith("*"))
                break;
            line = _reader->readLine().trimmed();
        }

        return true;
    }

    bool FITKAbaqusAdaptorMaterialElastic::readTypeLamina()
    {
        if (!_materialData)return false;
        auto tempElastic = _materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic);
        if (!tempElastic)return false;
        //获取数据
        Interface::FITKAbaMaterialElastic* elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //设置类型
        elasticData->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::Lamina);
        //文件应有的一次数据所具有的行数
        int row = (7 + _dependencies) % 8 ? (7 + _dependencies) / 8 + 1 : (7 + _dependencies) / 8;

        QString line;
        bool ok = false;
        int  num = 0;
        int index = 0;
        while (!_reader->atEnd())
        {
            line = _reader->readLine().trimmed();
            if (line.startsWith("*"))break;
            elasticData->setLaminaNumberOfRows(index + 1);
            //移除最后一个,预防干扰
            if (line.endsWith(','))line.chop(1);
            QStringList str;
            if (!line.trimmed().isEmpty())
                str = line.trimmed().split(',');
            for (int j = 0; j < 8 && j < str.size(); ++j)
            {
                ++num;
                if (num == 7)
                    if (str.at(j).trimmed().isEmpty())
                        continue;
                    else
                        elasticData->setUseTemperatureDependentData(true);
                //读取数据
                double v = str.at(j).trimmed().toDouble(&ok);
                if (!ok)return false;
                //E1
                if (num == 1)
                    elasticData->setLaminaE1(v, index);
                //E2
                else if (num == 2)
                    elasticData->setLaminaE2(v, index);
                //E3
                else if (num == 3)
                    elasticData->setLaminaNu12(v, index);
                //Nu12
                else if (num == 4)
                    elasticData->setLaminaG12(v, index);
                //Nu13
                else if (num == 5)
                    elasticData->setLaminaG13(v, index);
                //Nu23
                else if (num == 6)
                    elasticData->setLaminaG23(v, index);
                //Temperature
                else if (num == 7)
                    elasticData->setTemperature(v, index);
            }
            if (num % 8 != 0 || num / 8 == row)
            {
                ++index;
                if (num < 6)return false;
                num = 0;
            }
        }
        //无压缩与无拉伸
        while (!_reader->atEnd())
        {
            if (line.toLower() == "*no compression")
                elasticData->setNoCompression(true);
            else if (line.toLower() == "*no tension")
                elasticData->setNoTension(true);
            else if (line.startsWith("*"))
                break;
            line = _reader->readLine().trimmed();
        }
        return true;
    }

    bool FITKAbaqusAdaptorMaterialElastic::readTypeOrthotropics()
    {
        if (!_materialData)return false;
        auto tempElastic = _materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic);
        if (!tempElastic)return false;
        //获取数据
        Interface::FITKAbaMaterialElastic* elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //设置类型
        elasticData->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::Lamina);
        _reader->readLine();
        return true;
    }

    bool FITKAbaqusAdaptorMaterialElastic::readTypeAnIsotopic()
    {
        if (!_materialData)return false;
        auto tempElastic = _materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic);
        if (!tempElastic)return false;
        //获取数据
        Interface::FITKAbaMaterialElastic* elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //设置类型
        elasticData->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::AnIsotopic);
        _reader->readLine();
        return false;
    }

    bool FITKAbaqusAdaptorMaterialElastic::readTypeTraction()
    {
        if (!_materialData)return false;
        auto tempElastic = _materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic);
        if (!tempElastic)return false;
        //获取数据
        Interface::FITKAbaMaterialElastic* elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //设置类型
        elasticData->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::Traction);
        _reader->readLine();
        return false;
    }

    bool FITKAbaqusAdaptorMaterialElastic::readTypeCoupledTraction()
    {
        if (!_materialData)return false;
        auto tempElastic = _materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic);
        if (!tempElastic)return false;
        //获取数据
        Interface::FITKAbaMaterialElastic* elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //设置类型
        elasticData->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::CoupledTraction);
        _reader->readLine();
        return false;
    }

    bool FITKAbaqusAdaptorMaterialElastic::readTypeShear()
    {
        if (!_materialData)return false;
        auto tempElastic = _materialData->getMaterialBehavior(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic);
        if (!tempElastic)return false;
        //获取数据
        Interface::FITKAbaMaterialElastic* elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //设置类型
        elasticData->setMaterialElasticType(Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialElasticType::Shear);
        _reader->readLine();
        return false;
    }

    bool FITKAbaqusAdaptorMaterialElastic::writeTypeIsotroplc()
    {
        Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType materialType =
            Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic;
        _materialData = dynamic_cast<Interface::FITKAbaMaterial*>(_dataObj);
        if (!_materialData || !_writer) return false;
        //获得数据结构
        auto tempElastic = _materialData->getMaterialBehavior(materialType);
        //材料为空则返回
        if (!tempElastic) return true;
        auto elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;

        QTextStream* stream = _writer->getStream();
        int isotropiCcount = elasticData->getIsotropicNumberOfRows();
        if (isotropiCcount < 1) return false;
        double youngsModulus, poissonRatio, temperature;

        // 写出关键字
        *stream << "*Elastic" << endl;

        for (int i = 0; i < isotropiCcount; ++i)
        {
            youngsModulus = elasticData->getIsotropicYoungsModulus(i);
            poissonRatio = elasticData->getIsotropicPoisssonRatio(i);
            *stream << _writer->double2String(youngsModulus, 9, 18) << ",";
            *stream << _writer->double2String(poissonRatio, 9, 18);

            if (elasticData->getUseTemperatureDependentData())
            {
                temperature = elasticData->getIsotropicTemperature(i);
                *stream << "," << _writer->double2String(temperature, 9, 18);
            }
            *stream << endl;
        }
        //写出不可压缩状态
        if (elasticData->getNoCompression())
        {
            *stream << "*No Compression" << endl;
        }
        //写出不可拉伸的状态
        if (elasticData->getNoTension())
        {
            *stream << "*No Tension" << endl;
        }

        return true;
    }

    bool FITKAbaqusAdaptorMaterialElastic::writeTypeEngineeringConstants()
    {
        Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType materialType =
            Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic;
        _materialData = dynamic_cast<Interface::FITKAbaMaterial*>(_dataObj);
        if (!_materialData || !_writer) return false;
        //获得数据结构
        auto tempElastic = _materialData->getMaterialBehavior(materialType);
        //材料为空则返回
        if (!tempElastic) return true;
        auto elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //获取数据行
        int count = elasticData->getEngineeringConstantsNumberOfRows();
        if (count < 1) return false;
        //开始写出
        QTextStream* stream = _writer->getStream();
        QString lineOne = "*Elastic, type=ENGINEERING CONSTANTS";
        *stream << lineOne << endl;
        //写出数据
        bool isTemperature = elasticData->getUseTemperatureDependentData();
        for (int i = 0; i < count; ++i)
        {
            double e1 = elasticData->getEngineeringConstantsE1(i);
            double e2 = elasticData->getEngineeringConstantsE2(i);
            double e3 = elasticData->getEngineeringConstantsE3(i);
            double nu12 = elasticData->getEngineeringConstantsNu12(i);
            double nu13 = elasticData->getEngineeringConstantsNu13(i);
            double nu23 = elasticData->getEngineeringConstantsNu23(i);
            double g12 = elasticData->getEngineeringConstantsG12(i);
            double g13 = elasticData->getEngineeringConstantsG13(i);
            double g23 = elasticData->getEngineeringConstantsG23(i);
            double t = elasticData->getEngineeringConstantsTemperature(i);
            lineOne = QString("%1, %2, %3, %4, %5, %6, %7, %8").arg(_writer->double2String(e1, 7, 0)).arg(_writer->double2String(e2, 7, 0))
                .arg(_writer->double2String(e3, 7, 0)).arg(_writer->double2String(nu12, 7, 0)).arg(_writer->double2String(nu13, 7, 0))
                .arg(_writer->double2String(nu23, 7, 0)).arg(_writer->double2String(g12, 7, 0)).arg(_writer->double2String(g13, 7, 0));
            *stream << lineOne << endl;
            if (isTemperature)
                lineOne = QString("%1, %2").arg(_writer->double2String(g23, 7, 0)).arg(_writer->double2String(t, 7, 0));
            else
                lineOne = QString("%1, ").arg(_writer->double2String(g23, 7, 0));
            *stream << lineOne << endl;
        }
        //写出不可压缩状态
        if (elasticData->getNoCompression())
        {
            *stream << "*No Compression" << endl;
        }
        //写出不可拉伸的状态
        if (elasticData->getNoTension())
        {
            *stream << "*No Tension" << endl;
        }
        return true;
    }

    bool FITKAbaqusAdaptorMaterialElastic::writeTypeLamina()
    {
        Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType materialType =
            Interface::FITKAbaMaterialBehaviorEnum::FITKAbaMaterialBehaviorType::Elastic;
        _materialData = dynamic_cast<Interface::FITKAbaMaterial*>(_dataObj);
        if (!_materialData || !_writer) return false;
        //获得数据结构
        auto tempElastic = _materialData->getMaterialBehavior(materialType);
        //材料为空则返回
        if (!tempElastic) return true;
        auto elasticData = dynamic_cast<Interface::FITKAbaMaterialElastic*>(tempElastic);
        if (!elasticData) return false;
        //获取数据行
        int count = elasticData->getLaminaNumberOfRows();
        if (count < 1) return false;
        //开始写出
        QTextStream* stream = _writer->getStream();
        QString lineOne = "*Elastic, type=LAMINA";
        *stream << lineOne << endl;
        //写出数据
        bool isTemperature = elasticData->getUseTemperatureDependentData();
        for (int i = 0; i < count; ++i)
        {
            double e1 = elasticData->getLaminaE1(i);
            double e2 = elasticData->getLaminaE2(i);
            double nu12 = elasticData->getLaminaNu12(i);
            double g12 = elasticData->getLaminaG12(i);
            double g13 = elasticData->getLaminaG13(i);
            double g23 = elasticData->getLaminaG23(i);
            double t = elasticData->getEngineeringConstantsTemperature(i);
            lineOne = QString("%1, %2, %3, %4, %5, %6").arg(_writer->double2String(e1, 7, 0)).arg(_writer->double2String(e2, 7, 0))
                .arg(_writer->double2String(nu12, 7, 0)).arg(_writer->double2String(g12, 7, 0)).arg(_writer->double2String(g13, 7, 0))
                .arg(_writer->double2String(g23, 7, 0));
            if (isTemperature)
                lineOne += QString(", %1").arg(_writer->double2String(t, 7, 0));
            *stream << lineOne << endl;
        }
        //写出不可压缩状态
        if (elasticData->getNoCompression())
        {
            *stream << "*No Compression" << endl;
        }
        //写出不可拉伸的状态
        if (elasticData->getNoTension())
        {
            *stream << "*No Tension" << endl;
        }
        return true;
    }
}
